package com.hivekion.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hivekion.common.entity.TreeNode;
import com.hivekion.common.exception.BusinessException;
import com.hivekion.system.domain.BaseArea;
import com.hivekion.system.domain.vo.BaseAreaCreateInputVo;
import com.hivekion.system.domain.vo.BaseAreaModelVo;
import com.hivekion.system.domain.vo.BaseAreaUpdateInputVo;
import com.hivekion.system.domain.vo.BaseAreaViewVo;
import com.hivekion.system.mapper.BaseAreaMapper;
import com.hivekion.system.service.IBaseAreaService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import sun.reflect.generics.tree.Tree;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BaseAreaServiceImpl extends ServiceImpl<BaseAreaMapper, BaseArea> implements IBaseAreaService {

    @Override
    public List<BaseAreaViewVo> getAreaList(String parentId) {
        if (StringUtils.isBlank(parentId)) {
            parentId = "";
        }
        LambdaQueryWrapper<BaseArea> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BaseArea::getParentId, parentId);
        List<BaseAreaViewVo> result = new ArrayList<>();
        List<BaseArea> list = this.list(wrapper).stream()
                .sorted(Comparator.comparing(BaseArea::getSortCode))
                .collect(Collectors.toList());
        for (BaseArea baseArea : list) {
            BaseAreaViewVo baseAreaViewVo = new BaseAreaViewVo();
            BeanUtils.copyProperties(baseArea, baseAreaViewVo);
            result.add(baseAreaViewVo);
        }
        return result;
    }

    @Override
    public Boolean add(BaseAreaCreateInputVo vo) {
        if (StringUtils.isBlank(vo.getParentId())) {
            vo.setParentId("");
        }
        if (checkAreaCodeUnique("", vo.getCode())) {
            throw new BusinessException(500, "当前行政区域编号已存在，请重新输入！");
        }
        if (checkAreaNameUnique("", vo.getAreaName())) {
            throw new BusinessException(500, "当前行政区域已存在，请重新输入！");
        }
        BaseArea baseArea = new BaseArea();
        BeanUtils.copyProperties(vo, baseArea);
        return this.save(baseArea);
    }


    @Override
    public Boolean edit(BaseAreaUpdateInputVo vo) {
        BaseArea model = this.getById(vo.getId());
        if (model == null) {
            throw new BusinessException(500, "当前行政区域不存在！！");
        }
        if (checkAreaCodeUnique(vo.getId(), vo.getCode())) {
            throw new BusinessException(500, "当前行政区域编号已存在，请重新输入！");
        }
        if (checkAreaNameUnique(vo.getId(), vo.getAreaName())) {
            throw new BusinessException(500, "当前行政区域已存在，请重新输入！");
        }
        BeanUtils.copyProperties(vo, model);
        return this.saveOrUpdate(model);
    }

    @Override
    public BaseAreaModelVo getInfo(String key) {
        BaseArea model = this.getById(key);
        if (model == null) {
            throw new BusinessException(500, "当前行政区域不存在！！");
        }
        BaseAreaModelVo vo = new BaseAreaModelVo();
        BeanUtils.copyProperties(model, vo);
        return vo;
    }

    @Override
    public Boolean remove(String id) {
        LambdaQueryWrapper<BaseArea> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BaseArea::getParentId, id);
        int count = this.count(wrapper);
        if (count > 0) {
            throw new BusinessException(500, "该区域下有子区域，请先删除子区域！！");
        }
        return this.removeById(id);
    }


    /*
     * 判断行政区域名称是否存在
     * true 存在
     * */
    @Override
    public boolean checkAreaNameUnique(String key, String areaName) {
        LambdaQueryWrapper<BaseArea> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BaseArea::getAreaName, areaName)
                .ne(StringUtils.isNotBlank(key), BaseArea::getId, key);
        BaseArea one = this.getOne(wrapper);
        return one != null;
    }

    @Override
    public boolean checkAreaCodeUnique(String key, String areaCode) {
        LambdaQueryWrapper<BaseArea> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BaseArea::getCode, areaCode)
                .ne(StringUtils.isNotBlank(key), BaseArea::getId, key);
        BaseArea one = this.getOne(wrapper);
        return one != null;
    }

    @Override
    public List<TreeNode> getTreeNodes() {
        List<BaseArea> allList = this.list();
        return getChildrenNode(allList, "");
    }


    private List<TreeNode> getChildrenNode(List<BaseArea> allList, String parentId) {
        List<BaseArea> parentAreas = allList.stream().filter(x -> parentId.equals(x.getParentId())).collect(Collectors.toList());
        List<TreeNode> nodes = new ArrayList<>();
        parentAreas.forEach(item -> {
            TreeNode node = new TreeNode();
            node.setKey(item.getId());
            node.setTitle(item.getAreaName());

            long count = allList.stream().filter(x -> x.getParentId().equals(item.getId())).count();
            if (count > 0) {
                node.setChildren(getChildrenNode(allList, item.getId()));
            }
            nodes.add(node);
        });
        return nodes;
    }
}
